"""
自动选品业务模块
"""
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))

from typing import List, Dict, Any
from PyQt6.QtCore import QObject, pyqtSignal, QThread, pyqtSlot
from reqapi.get_csgo_page_list2 import GetCsgoPagedListV2Api
from reqapi.get_commodity_list import GetCommodityListApi
from com.scan_account_pool import ScanAccountPool
import time
import random
from datetime import datetime
import json
import traceback

class AutoSelectCommodity(QObject):
    """自动选品业务类"""
    
    # 日志信号
    log_signal = pyqtSignal(str)
    # 进度信号
    progress_signal = pyqtSignal(int, int)  # 当前进度, 总数
    # 选品结果信号
    result_signal = pyqtSignal(list)  # 选中的商品列表
    
    def __init__(self):
        super().__init__()
        self.account_pool = ScanAccountPool()
        self.csgo_api = None  # 延迟初始化
        self.account = None
        self.selected_commodities = []  # 选中的商品列表
        self.current_processed = 0  # 当前处理的商品数量
        self.total_items = 0  # 总商品数量
        
    def log(self, message: str):
        """发送日志消息"""
        try:
            self.log_signal.emit(message)
        except:
            print(message)
            
    def _init_api_with_account(self, account: dict):
        """使用账号信息初始化API"""
        self.csgo_api = GetCsgoPagedListV2Api(
            device_token=account.get('device_id', ''),
            device_id=account.get('device_id', ''),
            auth_token=account.get('uu_token', ''),
            uk=account.get('uk', '')
        )
        

        
    def _get_and_init_account(self):
        """获取账号并初始化API"""
        try:
            if not self.account:
                account_info = self.account_pool.get_accounts_with_intervals(1)[0]
                account = account_info['account']
                interval = account_info['interval']
                next_available_time = account_info['next_available_time']
            else:
                account = self.account
                interval = 0
                next_available_time = time.time()
            
            # 使用账号信息初始化API
            self.log("正在初始化API...")
            self._init_api_with_account(account)
            
            self.log(f"\n【使用账号】[{account.get('name', account.get('id', account.get('device_id', '未知')))}]查询饰品列表")
            self.log(f"【执行间隔】{interval} 秒")
            self.log(f"【下次可用时间】{datetime.fromtimestamp(next_available_time).strftime('%Y-%m-%d %H:%M:%S')}")
            
            # 等待到账号可用时间
            wait_time = max(0, next_available_time - time.time())
            if wait_time > 0:
                self.log(f"等待 {wait_time:.2f} 秒后开始查询...")
                time.sleep(wait_time)
            
            return account
        except Exception as e:
            self.log(f"获取和初始化账号时发生错误: {str(e)}")
            raise

    def _fetch_multi_page_items(self, account, wear_type, min_price, max_price, page_count=3):
        """
        获取多页商品数据
        
        Args:
            account: 账号信息
            wear_type: 商品类型
            min_price: 最低价格
            max_price: 最高价格
            page_count: 查询页数，默认3页
            
        Returns:
            list: 去重后的商品列表
        """
        try:
            self.log(f"正在获取{wear_type}类型的商品列表...")
            
            filter_map = {
                "Exterior": [wear_type],
                "Type": [
                    "CSGO_Type_Pistol_Unlimited",
                    "CSGO_Type_Rifle_Unlimited",
                    "CSGO_Type_SMG_Unlimited",
                    "CSGO_Type_Shotgun_Unlimited",
                    "CSGO_Type_Machinegun_Unlimited"
                ]
            }

            # self.log(f"filter_map: {json.dumps(filter_map, ensure_ascii=False)}")
            
            # 存储所有商品的集合，使用字典确保去重
            all_items_dict = {}
            
            # 查询多页数据
            for page in range(1, page_count + 1):
                self.log(f"正在获取第{page}页商品数据...")
                try:
                    # 调用API获取商品列表
                    response = self.csgo_api.execute(
                        filter_map=filter_map,
                        game_id=730,
                        list_sort_type=0,
                        list_type=10,
                        min_price=str(min_price),
                        max_price=str(max_price),
                        page_index=page,
                        page_size=100,
                        property_filter_tags=[],
                        sort_type=0,
                        sticker_abrade=0,
                        stickers_is_sort=False,
                        session_id=account.get('device_id', '')
                    )
                    
                    # self.log(f"API响应: {json.dumps(response, ensure_ascii=False)}")

                    # 等待1-3秒，以免太频繁的访问API
                    wait_time = random.uniform(1, 3)
                    self.log(f"等待 {wait_time:.2f} 秒后继续...")
                    time.sleep(wait_time)
                    
                    if not response or response.get('Code') != 0:
                        self.log(f"获取第{page}页商品列表失败: {response.get('Message', '未知错误')}")
                        continue
                        
                    # 获取商品列表数据
                    items = response.get('Data', {}).get('categoryList', [])
                    if not items:
                        self.log(f"第{page}页未找到符合条件的商品")
                        continue
                    
                    self.log(f"第{page}页获取到{len(items)}个商品")
                    
                    # 将商品添加到字典中，使用商品ID作为键以实现去重
                    for item in items:
                        item_id = item.get('Id')
                        if item_id:
                            all_items_dict[item_id] = item
                except Exception as e:
                    self.log(f"获取第{page}页数据时发生错误: {str(e)}")
                    continue

            # 转换为列表
            items = list(all_items_dict.values())
            
            if not items:
                self.log("未找到符合条件的商品")
                return []
                
            self.log(f"总共找到{len(items)}个不重复商品")
            return items
        except Exception as e:
            self.log(f"获取多页商品数据时发生错误: {str(e)}")
            raise

    def select_commodities(self, wear_type: str, min_wear: float, max_wear: float,
                         min_price: float, max_price: float, premium_rate: float,
                         min_count: int) -> List[Dict[str, Any]]:
        """
        自动选品
        
        Args:
            wear_type: 外观类型，如"久经沙场"
            min_wear: 最小磨损值
            max_wear: 最大磨损值
            min_price: 最低价格
            max_price: 最高价格
            premium_rate: 溢价率(%)
            min_count: 最小在售数量
            
        Returns:
            选中的商品列表
        """
        try:
            self.log("开始选择商品...")
            # 1. 获取并初始化账号
            account = self._get_and_init_account()
            
            # 2. 获取多页商品列表
            items = self._fetch_multi_page_items(account, wear_type, min_price, max_price)
            
            if not items:
                self.log("未找到符合条件的商品")
                return []
                
            self.log(f"开始筛选在售量大于{min_count}的商品...")
            
            # 筛选在售量大于最小在售量的商品
            filtered_items = []
            for item in items:
                on_sale_count = item.get('OnSaleCount', 0)
                if on_sale_count >= min_count:
                    filtered_items.append(item)
                    
            self.log(f"筛选后剩余{len(filtered_items)}个商品")
            
            # 遍历筛选后的商品列表
            self.total_items = len(filtered_items)
            self.current_processed = 0  # 当前处理的商品数量
            
            # 发送初始进度
            self.progress_signal.emit(0, self.total_items)
            self.log(f"开始检查{self.total_items}个商品...")
            
            # 清空已选商品列表
            self.selected_commodities = []
            
            # 获取账号列表
            accounts = self.account_pool.get_accounts_with_intervals(self.total_items)
            
            # 为每个商品创建一个线程
            for i, (item, account_info) in enumerate(zip(filtered_items, accounts)):
                commodity_name = item.get('Name', '')
                template_id = item.get('Id', '')
                
                account = account_info['account']
                
                # 创建API实例
                commodity_api = GetCommodityListApi(
                    device_token=account.get('device_id', ''),
                    device_id=account.get('device_id', ''),
                    auth_token=account.get('uu_token', ''),
                    uk=account.get('uk', ''),
                    user_id=account.get('uu_user_id', '')
                )
                
                self.log(f"创建商品 {commodity_name} 的查询线程，账号下次可用时间: {datetime.fromtimestamp(account_info['next_available_time']).strftime('%Y-%m-%d %H:%M:%S')}")
                
                # 创建并启动线程
                thread = CommodityThread(
                    commodity_api, 
                    max_wear, 
                    min_wear, 
                    max_price, 
                    template_id,
                    commodity_name,
                    item,
                    premium_rate,
                    account_info,
                    self.process_sell_list
                )
                thread.start()
                thread.wait()  # 等待当前线程完成后再处理下一个
            
            self.log(f"选品完成，共找到{len(self.selected_commodities)}个符合条件的商品")
            return self.selected_commodities
            
        except Exception as e:
            self.log(f"选品过程中发生错误: {str(e)}")
            return []
            
    @pyqtSlot(object, str, str, float, float, float, object, object, str)
    def process_sell_list(self, sell_list, commodity_name, template_id, max_wear, min_wear, premium_rate, commodity_data, message=None):
        """处理商品出售列表"""
        try:
            # 更新处理进度
            self.current_processed += 1
            self.progress_signal.emit(self.current_processed, self.total_items)

            if message:
                self.log(message)
                return
                
            if sell_list is None:
                self.log(f"获取商品 {commodity_name} 出售列表失败: 返回为空")
                return
                
            if not isinstance(sell_list, list):
                self.log(f"获取商品 {commodity_name} 出售列表失败: API返回格式错误")
                return
                
            if not sell_list:
                self.log(f"商品 {commodity_name} 没有在售商品，跳过")
                return
            
            self.log(f"开始处理在售列表，共{len(sell_list)}个商品")
            self.log(f"磨损值范围：{min_wear} - {max_wear}")
            
            # 从饰品数据中获取市场参考价和在售数量
            if not commodity_data or "Price" not in commodity_data:
                self.log(f"商品 {commodity_name} 无法获取市场参考价，跳过")
                return
                
            market_price = float(commodity_data.get("Price", 0))
            if market_price <= 0:
                self.log(f"商品 {commodity_name} 的市场参考价为0，跳过")
                return

            # 从饰品数据中获取在售数量
            on_sale_count = commodity_data.get("OnSaleCount", 0)
            
            # 获取目标售价（第一个在售商品的价格）
            target_price = float(sell_list[0].get("Price", 0)) if sell_list else 0
            if target_price <= 0:
                self.log(f"商品 {commodity_name} 无法获取目标售价，跳过")
                return
            
            # 计算平均价格
            total_price = sum(float(item.get("Price", 0)) for item in sell_list)
            avg_price = total_price / len(sell_list) if sell_list else 0
            
            # 计算溢价率：(平均价格 - 市场参考价) / 市场参考价 * 100
            premium = (avg_price - market_price) / market_price * 100
            
            self.log(f"商品 {commodity_name} 的市场参考价: {market_price:.2f}")
            self.log(f"商品 {commodity_name} 的目标售价: {target_price:.2f}")
            self.log(f"商品 {commodity_name} 的平均价格: {avg_price:.2f}")
            self.log(f"商品 {commodity_name} 的溢价率: {premium:.2f}%")
            
            # print("commodity_data:", commodity_data)
            # 如果溢价率符合要求，添加到选中列表
            if premium >= premium_rate:
                selected_commodity = {
                    "template_id": str(template_id),  # 确保转换为字符串
                    "name": commodity_data.get("CommodityName", ""),      # 确保转换为字符串
                    "wear": f"{min_wear}-{max_wear}",
                    "price": f"{market_price:.2f}",
                    "target_price": f"{target_price:.2f}",
                    "premium_rate": f"{premium:.2f}%",
                    "count": str(on_sale_count)       # 确保转换为字符串
                }
                self.selected_commodities.append(selected_commodity)
                # 实时发送结果信号
                self.result_signal.emit([selected_commodity])
                self.log(f"商品 {commodity_name} 符合条件，已添加到选中列表")
            else:
                self.log(f"商品 {commodity_name} 溢价率不符合要求，跳过")
                
        except Exception as e:
            self.log(f"处理商品 {commodity_name} 时发生错误: {str(e)}")
            traceback.print_exc()

class CommodityThread(QThread):
    def __init__(self, commodity_api, max_wear, min_wear, max_price, template_id, commodity_name, commodity, premium_rate, account_info, callback):
        super().__init__()
        self.commodity_api = commodity_api
        self.max_wear = max_wear
        self.min_wear = min_wear
        self.max_price = max_price
        self.template_id = template_id
        self.commodity_name = commodity_name
        self.commodity = commodity
        self.premium_rate = premium_rate
        self.account_info = account_info
        self.callback = callback
        
    def run(self):
        try:
            print(f"[线程开始] 处理商品: {self.commodity_name}")
            # 等待账号可用
            next_available_time = self.account_info.get('next_available_time', 0)
            if next_available_time > time.time():
                wait_time = next_available_time - time.time()
                print(f"[等待] 账号需要等待 {wait_time:.2f} 秒后可用")
                self.callback(None, self.commodity_name, self.template_id, self.max_wear, self.min_wear, self.premium_rate, self.commodity, f"等待账号可用，还需 {wait_time:.2f} 秒...")
                time.sleep(wait_time)
            
            print(f"[查询] 开始获取商品在售列表")
            sell_list = self.commodity_api.execute(
                max_abrade=str(self.max_wear),
                min_abrade=str(self.min_wear),
                max_price=str(self.max_price),
                template_id=str(self.template_id),
                page_size=5
            )
            
            if sell_list is None:
                print(f"[错误] 获取商品出售列表失败: 返回为空")
                self.callback(None, self.commodity_name, self.template_id, self.max_wear, self.min_wear, self.premium_rate, self.commodity, "获取商品出售列表失败: 返回为空")
                return
                
            if "Data" not in sell_list:
                print(f"[错误] 获取商品出售列表失败: 返回数据中没有Data字段")
                self.callback(None, self.commodity_name, self.template_id, self.max_wear, self.min_wear, self.premium_rate, self.commodity, "获取商品出售列表失败: 返回数据中没有Data字段")
                return
                
            if "CommodityList" not in sell_list["Data"]:
                print(f"[错误] 获取商品出售列表失败: 返回数据中没有CommodityList字段")
                self.callback(None, self.commodity_name, self.template_id, self.max_wear, self.min_wear, self.premium_rate, self.commodity, "获取商品出售列表失败: 返回数据中没有CommodityList字段")
                return
                
            sell_items = sell_list["Data"]["CommodityList"]
            print(f"[查询] 获取到 {len(sell_items)} 个在售商品")
            self.callback(sell_items, self.commodity_name, self.template_id, self.max_wear, self.min_wear, self.premium_rate, self.commodity, None)
            print(f"[线程结束] {self.commodity_name} 处理完成")
            
        except Exception as e:
            print(f"[错误] 处理商品 {self.commodity_name} 时发生错误: {str(e)}")
            traceback.print_exc()
            self.callback(None, self.commodity_name, self.template_id, self.max_wear, self.min_wear, self.premium_rate, self.commodity, f"查询出错: {str(e)}")

def main():
    """测试入口"""
    # 创建自动选品实例
    auto_select = AutoSelectCommodity()
    
    # 连接信号
    auto_select.log_signal.connect(lambda msg: print(f"[LOG] {msg}"))
    auto_select.progress_signal.connect(lambda cur, total: print(f"[PROGRESS] {cur}/{total}"))
    auto_select.result_signal.connect(lambda results: print(f"[RESULT] 找到{len(results)}个商品"))
    
    # 设置选品参数
    params = {
        'wear_type': "WearCategory1",  # 外观类型
        'min_wear': 0.07,  # 最小磨损值
        'max_wear': 0.08,  # 最大磨损值
        'min_price': 5,  # 最低价格
        'max_price': 100,  # 最高价格
        'premium_rate': 10,  # 溢价率
        'min_count': 400  # 最小在售数量
    }
    
    # 执行选品
    try:
        results = auto_select.select_commodities(**params)
        print("\n选品结果:")
        for item in results:
            print(f"商品名称: {item['name']}")
            print(f"磨损范围: {item['wear']}")
            print(f"市场价: {item['price']}")
            print(f"目标售价: {item['target_price']}")
            print(f"溢价率: {item['premium_rate']}")
            print(f"在售数量: {item['count']}")
            print(f"模板ID: {item['template_id']}")
            print("-" * 50)
    except Exception as e:
        print(f"选品过程中发生错误: {str(e)}")

if __name__ == "__main__":
    main()
